/******************************************************************
 * Copyright @ 2023 广州牛师帮科技文化有限公司. All rights reserverd.
 * @file   src\pages\Main\hooks\useNavItems.ts
 * @author 朱剑豪
 * @date   2023/10/23 14:44
 * @desc   主菜单信息|导航信息|导航菜单信息
 ******************************************************************/

import type { ItemType, MenuItemGroupType, MenuItemType, SubMenuType } from "antd/es/menu/interface";
import React, { useCallback, useMemo } from "react";
import { NavItemLabel } from "../components/NavItemLabel";

type MenuItem = MenuItemType | MenuItemGroupType | SubMenuType;
export type NavItem<T> = T | [T, NavItem<T>[]]
export interface IUseNavItemsOpts<T extends string> {
  is_page: (path: T) => boolean;
  get_icon: (path: T) => React.ReactNode;
  get_name: (path: T) => string;
  has_permission: (path: T) => boolean;
  root: [T, NavItem<T>[]];
}
export default function useNavItems<T extends string>(opts: IUseNavItemsOpts<T>) {
  const { is_page, get_icon, get_name, has_permission, root } = opts;
  const list_menu_item = useCallback((root: NavItem<T>) => {
    const new_menu_info = (key: T, children?: MenuItem[]): MenuItem => {
      return ({
        key,
        label: <NavItemLabel label={get_name(key)} path={key} is_page={is_page} />,
        icon: get_icon(key),
        children,
      })
    }
    const nav_item_2_menu_item_info = (item: NavItem<T>): MenuItem | null => {
      if (typeof item === 'string') {
        if (!has_permission(item)) return null
        const ret = new_menu_info(item)
        if (ret) ret.type = 'item';
        return ret
      }
      const [key, children] = item;
      if (!has_permission(key)) return null;

      const sub_menu_item_list: MenuItem[] = []
      for (const child of children) {
        const sub_menu_item = nav_item_2_menu_item_info(child)
        if (!sub_menu_item) continue;
        sub_menu_item_list.push(sub_menu_item)
      }
      const ret = new_menu_info(key, sub_menu_item_list)
      if (ret) ret.type = 'submenu'
      return ret;
    }
    return (nav_item_2_menu_item_info(root) as SubMenuType).children
  }, [get_icon, get_name, has_permission, is_page])

  return useMemo<ItemType[]>(() => list_menu_item(root), [list_menu_item, root])
}